/*
 * 
 */

package android.bluebox.view;

import java.util.ArrayList;
import java.util.Calendar;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluebox.R;
import android.bluebox.model.LocationResult;
import android.bluebox.model.StaticBox;
import android.bluebox.model.Workspace;
import android.bluebox.model.WorkspaceAdapter;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class WorkspaceListView extends Activity {

	ListView lvWorkspace;
	ArrayList<Workspace> wsList;
	WorkspaceAdapter cba;

	boolean isListAll = true;
	boolean isNearBy = false;

	TextView txtHeader;
	TextView txtNumberOfWorkspaces;

	LocationResult currentLocation = new LocationResult(-1, -1);

	LocationManager mlocManager;
	LocationListener mlocListener;

	boolean foundLocation = false;

	Intent intent;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.workspacelist);

		txtHeader = (TextView) findViewById(R.id.txt_bluebox_header);
		txtHeader.setText(StaticBox.getCurrentWorkspaceName());
		txtNumberOfWorkspaces = (TextView) findViewById(R.id.wsl_number);

		lvWorkspace = (ListView) findViewById(R.id.wsl_list);

		cba = new WorkspaceAdapter(this, wsList);
		refreshWorkspaceList();
		lvWorkspace.setOnItemClickListener(chooseWorkspace);
	}

	public ArrayList<Workspace> loadAllWorkspaces() {
		StaticBox.dbBox.setContext(this);
		String strNumberOfWorkspace = String.valueOf(StaticBox.dbBox.getNumberOfWorkspaces());
		txtNumberOfWorkspaces.setText(strNumberOfWorkspace);
		ArrayList<Workspace> list = StaticBox.dbBox.getAllWorkspaces();
		return list; 
	}

	public ArrayList<Workspace> loadWorkspaceForList() {
		if (isListAll) {
			if (isNearBy) {
				ArrayList<Workspace> wsListAll = loadAllWorkspaces();

				/*
				 * Sort the list
				 */
				for (int i = 0; i < wsListAll.size() - 1; i++) {
					float minDistance = StaticBox.distance(currentLocation, wsListAll.get(i).getLocation());
					int minJ = i;
					for (int j = i + 1; j < wsListAll.size(); j++) {
						float dj = StaticBox.distance(currentLocation, wsListAll.get(j).getLocation());
						if (dj < minDistance) {
							minDistance = dj;
							minJ = j;
						}
					}
					if (minJ != i) {
						Workspace temp = wsListAll.get(i);
						wsListAll.set(i, wsListAll.get(minJ));
						wsListAll.set(minJ, temp);
					}
				}
				/*
				 * End of sorting
				 */
				isNearBy = false;
				return wsListAll;

			} else
				return loadAllWorkspaces();
		} else {
			ArrayList<Workspace> wsListAll = loadAllWorkspaces();
			ArrayList<Workspace> list = new ArrayList<Workspace>();
			for (Workspace ws : wsListAll) {
				if (ws.isAvailable())
					list.add(ws);
			}
			return list;
		}
	}

	public void refreshWorkspaceList() {
		wsList = loadWorkspaceForList();
		cba.setArraylist(wsList);
		cba.notifyDataSetChanged();
		lvWorkspace.setAdapter(cba);
	}

	/*
	 * Catch choosing workspace event
	 */
	OnItemClickListener chooseWorkspace = new OnItemClickListener() {

		@Override
		public void onItemClick(AdapterView<?> a, View v, int position, long id) {

			/*
			 * Get clicked item
			 */
			final Workspace ws = (Workspace) lvWorkspace.getItemAtPosition(position);

			/*
			 * Create list of option: Connect, Edit, Delete
			 */
			final CharSequence[] workspaceOption;
			if (ws.getId() == StaticBox.currentWorkspaceId) {
				workspaceOption = new CharSequence[]{"Disconnect", "Edit", "Delete", "Open"};
			} else {
				workspaceOption = new CharSequence[]{"Connect", "Edit", "Delete", "Open"};
			}
			/*
			 * Create dialog
			 */
			AlertDialog.Builder builder = new AlertDialog.Builder(WorkspaceListView.this);
			builder.setTitle(ws.getName() + " Options");
			builder.setItems(workspaceOption, new OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int item) {
					switch (item) {

					/*
					 * Connect
					 */
					case 0:
						if (workspaceOption[0].equals("Connect")) {
							new ConnectToHost().execute(ws);
						} else {
							StaticBox.netBox.disconect();
							StaticBox.currentWorkspaceId = -1;
							txtHeader.setText(StaticBox.getCurrentWorkspaceName());
						}
						break;

						/*
						 * Edit
						 */
					case 1:
						intent = new Intent(WorkspaceListView.this, WorkspaceDetailView.class);
						intent.putExtra("wsId", ws.getId());
						startActivityForResult(intent, 1);
						break;

						/*
						 * Delete
						 */
					case 2:
						deleteWorkspace(ws);
						break;

						/*
						 * Load attribute
						 */
					case 3:
						openWorkspace(ws.getId());
						break;
					}
				}
			});
			AlertDialog dialog = builder.create();
			dialog.show();
		}
	};

	/*
	 * Create Option Menu
	 */
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.layout.workspacelist_optionmenu, menu);
		return true;
	}

	/*
	 * Create event for Option Menu
	 */
	public boolean onOptionsItemSelected(MenuItem item) {

		Intent intent; 

		switch (item.getItemId()) {

		case R.id.wsl_new_ws:
			intent = new Intent(WorkspaceListView.this, WorkspaceDetailView.class);
			intent.putExtra("ws_id", 0);
			startActivityForResult(intent, 0);
			break;

		case R.id.wsl_home:
			intent = new Intent(WorkspaceListView.this, FirstView.class);
			startActivity(intent);
			finish();
			break;

		case R.id.wsl_view_all:
			isListAll = true;
			isNearBy = false;
			refreshWorkspaceList();
			break;

		case R.id.wsl_view_available:
			isListAll = false;
			isNearBy = false;
			refreshWorkspaceList();
			break;

		case R.id.wsl_view_nearby:
			isListAll = true;
			isNearBy = true;
			getNewGPS();
			new LocationControl().execute(getApplicationContext());
			break;
		}
		return true;
	}

	protected void onResume() {
		super.onResume();
		refreshWorkspaceList();
	}

	public void deleteWorkspace(Workspace ws) {
		StaticBox.dbBox.deleteWorkspace(ws.getId());
		refreshWorkspaceList();
	}

	public boolean requestToConnect(String hostIP) {

		if (hostIP != null) {
			return (StaticBox.netBox.requestToConnect(hostIP));
		} else {
			StaticBox.makeToast(this, "Host IP is empty. Please edit host IP of workspace before connecting");
			return false;
		}
	}

	private void openWorkspace(int wsId) {
		intent = new Intent(WorkspaceListView.this, AValueListView.class);
		intent.putExtra("typeId", 2);
		intent.putExtra("filterId", wsId);	// Send wsId of tag you want to open
		startActivity(intent);
	}

	public void resetLastVisit(Workspace ws) {
		ws.resetLastVisited();
		StaticBox.dbBox.updateWorkspace(ws);
	}

	public void verifyPairCode(final Workspace ws) {

		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		alert.setTitle("Pair code");

		final EditText edtPairCode = new EditText(this);
		edtPairCode.setText("");
		alert.setView(edtPairCode);

		alert.setPositiveButton("Connect", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int button) {
				String code = edtPairCode.getText().toString().trim(); 
				if (code.length() > 0) {
					if (StaticBox.netBox.verifyPairCode(code, ws.getHostIP())) {
						resetLastVisit(ws);
						Toast.makeText(getBaseContext(), "Connected!", Toast.LENGTH_SHORT).show();
						StaticBox.currentWorkspaceId = ws.getId();
						txtHeader.setText(StaticBox.getCurrentWorkspaceName());
						openWorkspace(ws.getId());
					}
				} else {
					Toast.makeText(getBaseContext(), "Please input pair code", Toast.LENGTH_SHORT).show();
				}
			}
		});

		alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int button) {
			}
		});
		alert.show();
	}

	public class ConnectToHost extends AsyncTask<Workspace, Void, Workspace> {

		private final ProgressDialog dialog = new ProgressDialog(WorkspaceListView.this);

		protected void onPreExecute() {
			this.dialog.setTitle("Connecting to server");
			this.dialog.setMessage("Please wait...");
			this.dialog.show();
		}

		@Override
		protected Workspace doInBackground(Workspace... ws) {		
			return (requestToConnect(ws[0].getHostIP()))? ws[0] : null;
		}

		protected void onProgressUpdate(final Void unused) {
		}

		protected void onPostExecute(Workspace ws) {
			if (this.dialog.isShowing())
				this.dialog.dismiss();

			if (ws != null)
				verifyPairCode(ws);

			Toast.makeText(getBaseContext(), (ws != null)? "Workspace is available" : "Workspace not available", Toast.LENGTH_SHORT).show();
		}
	}

	/*
	 * GPS ZONE
	 */
	public void getNewGPS() {
		mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		mlocListener = new MyLocationListener();
		mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
		mlocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mlocListener);
	}

	public void removeUpdates() {
		mlocManager.removeUpdates(mlocListener);
	}

	public void update() {
		mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
		mlocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mlocListener);
	}

	public class MyLocationListener implements LocationListener {
		public void onLocationChanged(Location loc) {
			foundLocation = false;
			float latitude = (float) loc.getLatitude();
			float longitude = (float) loc.getLongitude();
			currentLocation.setLocation(latitude, longitude);
			StaticBox.currentLocation = currentLocation;

			String strLocation = "Latitude = " + latitude + "\nLongitude = " + longitude;
			StaticBox.makeToast(getApplicationContext(), strLocation);
			foundLocation = true;
			removeUpdates();
		}

		@Override
		public void onProviderDisabled(String provider) {
			Toast.makeText(getApplicationContext(), "Gps Disable", Toast.LENGTH_SHORT).show();
			foundLocation = true;
		}

		@Override
		public void onProviderEnabled(String provider) {
			Toast.makeText(getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	}

	private class LocationControl extends AsyncTask<Context, Void, Void> {
		private final ProgressDialog dialog = new ProgressDialog(WorkspaceListView.this);

		protected void onPreExecute() {
			this.dialog.setTitle("Searching location");
			this.dialog.setMessage("Please wait...");
			this.dialog.show();
		}

		@Override
		protected Void doInBackground(Context... params) {
			Long t = Calendar.getInstance().getTimeInMillis();
			while (!foundLocation && Calendar.getInstance().getTimeInMillis() - t < 15000) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			return null;
		}

		protected void onPostExecute(final Void unused)
		{
			if(this.dialog.isShowing()) {
				this.dialog.dismiss();
			}
			if (currentLocation.getLatitude() < 0){
				StaticBox.makeToast(getBaseContext(), "can not detect location");
			} else {
				isNearBy = true;
				refreshWorkspaceList();
			}
			removeUpdates();
		}
	}

	/*
	 * END OF GPS ZONE
	 */
}
